//package oc.tm.sg.registry.core.integration;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//import java.util.concurrent.ConcurrentHashMap;
//
//import javassist.util.proxy.ProxyFactory;
//
//import javax.xml.ws.spi.Invoker;
//
//import oc.tm.sg.registry.common.Constants;
//import oc.tm.sg.registry.common.URL;
//import oc.tm.sg.registry.common.extension.ExtensionLoader;
//import oc.tm.sg.registry.common.utils.StringUtils;
//import oc.tm.sg.registry.common.utils.UrlUtils;
//import oc.tm.sg.registry.core.NotifyListener;
//import oc.tm.sg.registry.core.Registry;
//import oc.tm.sg.registry.core.RegistryFactory;
//import oc.tm.sg.registry.core.RegistryService;
//
//import org.apache.log4j.Logger;
//import org.apache.log4j.spi.Configurator;
//import org.slf4j.LoggerFactory;
//
///**
// * RegistryProtocol
// * 
// * @author william.liangf
// * @author chao.liuc
// */
//public class RegistryProtocol implements Protocol {
//
//    private Cluster cluster;
//    
//    public void setCluster(Cluster cluster) {
//        this.cluster = cluster;
//    }
//    
//    private Protocol protocol;
//    
//    public void setProtocol(Protocol protocol) {
//        this.protocol = protocol;
//    }
//
//    private RegistryFactory registryFactory;
//    
//    public void setRegistryFactory(RegistryFactory registryFactory) {
//        this.registryFactory = registryFactory;
//    }
//
//    private ProxyFactory proxyFactory;
//    
//    public void setProxyFactory(ProxyFactory proxyFactory) {
//        this.proxyFactory = proxyFactory;
//    }
//
//    public int getDefaultPort() {
//        return 9090;
//    }
//    
//    private static RegistryProtocol INSTANCE;
//
//    public RegistryProtocol() {
//        INSTANCE = this;
//    }
//    
//    public static RegistryProtocol getRegistryProtocol() {
//        if (INSTANCE == null) {
//            ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(Constants.REGISTRY_PROTOCOL); // load
//        }
//        return INSTANCE;
//    }
//    
//    private final Map<URL, NotifyListener> overrideListeners = new ConcurrentHashMap<URL, NotifyListener>();
//    
//    public Map<URL, NotifyListener> getOverrideListeners() {
//		return overrideListeners;
//	}
//
//	//用于解决rmi重复暴露端口冲突的问题，已经暴露过的服务不再重新暴露
//    //providerurl <--> exporter
//    private final Map<String, ExporterChangeableWrapper<?>> bounds = new ConcurrentHashMap<String, ExporterChangeableWrapper<?>>();
//    
//    private final static Logger logger = Logger.getLogger(RegistryProtocol.class);
//    
//    public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
//        //export invoker
//        final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
//        //registry provider
//        final Registry registry = getRegistry(originInvoker);
//        final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
//        registry.register(registedProviderUrl);
//        // 订阅override数据
//        // FIXME 提供者订阅时，会影响同一JVM即暴露服务，又引用同一服务的的场景，因为subscribed以服务名为缓存的key，导致订阅信息覆盖。
//        final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registedProviderUrl);
//        final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl);
//        overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
//        registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
//        //保证每次export都返回一个新的exporter实例
//        return new Exporter<T>() {
//            public Invoker<T> getInvoker() {
//                return exporter.getInvoker();
//            }
//            public void unexport() {
//            	try {
//            		exporter.unexport();
//            	} catch (Throwable t) {
//                	logger.warn(t.getMessage(), t);
//                }
//                try {
//                	registry.unregister(registedProviderUrl);
//                } catch (Throwable t) {
//                	logger.warn(t.getMessage(), t);
//                }
//                try {
//                	overrideListeners.remove(overrideSubscribeUrl);
//                	registry.unsubscribe(overrideSubscribeUrl, overrideSubscribeListener);
//                } catch (Throwable t) {
//                	logger.warn(t.getMessage(), t);
//                }
//            }
//        };
//    }
//    
//    @SuppressWarnings("unchecked")
//    private <T> ExporterChangeableWrapper<T>  doLocalExport(final Invoker<T> originInvoker){
//        String key = getCacheKey(originInvoker);
//        ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
//        if (exporter == null) {
//            synchronized (bounds) {
//                exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
//                if (exporter == null) {
//                    final Invoker<?> invokerDelegete = new InvokerDelegete<T>(originInvoker, getProviderUrl(originInvoker));
//                    exporter = new ExporterChangeableWrapper<T>((Exporter<T>)protocol.export(invokerDelegete), originInvoker);
//                    bounds.put(key, exporter);
//                }
//            }
//        }
//        return (ExporterChangeableWrapper<T>) exporter;
//    }
//    
//    /**
//     * 对修改了url的invoker重新export
//     * @param originInvoker
//     * @param newInvokerUrl
//     */
//    @SuppressWarnings("unchecked")
//    private <T> void doChangeLocalExport(final Invoker<T> originInvoker, URL newInvokerUrl){
//        String key = getCacheKey(originInvoker);
//        final ExporterChangeableWrapper<T> exporter = (ExporterChangeableWrapper<T>) bounds.get(key);
//        if (exporter == null){
//            logger.warn(new IllegalStateException("error state, exporter should not be null"));
//            return ;//不存在是异常场景 直接返回 
//        } else {
//            final Invoker<T> invokerDelegete = new InvokerDelegete<T>(originInvoker, newInvokerUrl);
//            exporter.setExporter(protocol.export(invokerDelegete));
//        }
//    }
//
//    /**
//     * 根据invoker的地址获取registry实例
//     * @param originInvoker
//     * @return
//     */
//    private Registry getRegistry(final Invoker<?> originInvoker){
//        URL registryUrl = originInvoker.getUrl();
//        if (Constants.REGISTRY_PROTOCOL.equals(registryUrl.getProtocol())) {
//            String protocol = registryUrl.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_DIRECTORY);
//            registryUrl = registryUrl.setProtocol(protocol).removeParameter(Constants.REGISTRY_KEY);
//        }
//        return registryFactory.getRegistry(registryUrl);
//    }
//
//    /**
//     * 返回注册到注册中心的URL，对URL参数进行一次过滤
//     * @param originInvoker
//     * @return
//     */
//    private URL getRegistedProviderUrl(final Invoker<?> originInvoker){
//        URL providerUrl = getProviderUrl(originInvoker);
//        //注册中心看到的地址
//        final URL registedProviderUrl = providerUrl.removeParameters(getFilteredKeys(providerUrl)).removeParameter(Constants.MONITOR_KEY);
//        return registedProviderUrl;
//    }
//    
//    private URL getSubscribedOverrideUrl(URL registedProviderUrl){
//    	return registedProviderUrl.setProtocol(Constants.PROVIDER_PROTOCOL)
//                .addParameters(Constants.CATEGORY_KEY, Constants.CONFIGURATORS_CATEGORY, 
//                        Constants.CHECK_KEY, String.valueOf(false));
//    }
//
//    /**
//     * 通过invoker的url 获取 providerUrl的地址
//     * @param origininvoker
//     * @return
//     */
//    private URL getProviderUrl(final Invoker<?> origininvoker){
//        String export = origininvoker.getUrl().getParameterAndDecoded(Constants.EXPORT_KEY);
//        if (export == null || export.length() == 0) {
//            throw new IllegalArgumentException("The registry export url is null! registry: " + origininvoker.getUrl());
//        }
//        
//        URL providerUrl = URL.valueOf(export);
//        return providerUrl;
//    }
//
//    /**
//     * 获取invoker在bounds中缓存的key
//     * @param originInvoker
//     * @return
//     */
//    private String getCacheKey(final Invoker<?> originInvoker){
//        URL providerUrl = getProviderUrl(originInvoker);
//        String key = providerUrl.removeParameters("dynamic", "enabled").toFullString();
//        return key;
//    }
//    
//    @SuppressWarnings("unchecked")
//	public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
//        url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY);
//        Registry registry = registryFactory.getRegistry(url);
//        if (RegistryService.class.equals(type)) {
//        	return proxyFactory.getInvoker((T) registry, type, url);
//        }
//
//        // group="a,b" or group="*"
//        Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY));
//        String group = qs.get(Constants.GROUP_KEY);
//        if (group != null && group.length() > 0 ) {
//            if ( ( Constants.COMMA_SPLIT_PATTERN.split( group ) ).length > 1
//                    || "*".equals( group ) ) {
//                return doRefer( getMergeableCluster(), registry, type, url );
//            }
//        }
//        return doRefer(cluster, registry, type, url);
//    }
//    
//    private Cluster getMergeableCluster() {
//        return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension("mergeable");
//    }
//    
//    private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
//        RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url);
//        directory.setRegistry(registry);
//        directory.setProtocol(protocol);
//        URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, NetUtils.getLocalHost(), 0, type.getName(), directory.getUrl().getParameters());
//        if (! Constants.ANY_VALUE.equals(url.getServiceInterface())
//                && url.getParameter(Constants.REGISTER_KEY, true)) {
//            registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY,
//                    Constants.CHECK_KEY, String.valueOf(false)));
//        }
//        directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY, 
//                Constants.PROVIDERS_CATEGORY 
//                + "," + Constants.CONFIGURATORS_CATEGORY 
//                + "," + Constants.ROUTERS_CATEGORY));
//        return cluster.join(directory);
//    }
//
//    //过滤URL中不需要输出的参数(以点号开头的)
//    private static String[] getFilteredKeys(URL url) {
//        Map<String, String> params = url.getParameters();
//        if (params != null && !params.isEmpty()) {
//            List<String> filteredKeys = new ArrayList<String>();
//            for (Map.Entry<String, String> entry : params.entrySet()) {
//                if (entry != null && entry.getKey() != null && entry.getKey().startsWith(Constants.HIDE_KEY_PREFIX)) {
//                    filteredKeys.add(entry.getKey());
//                }
//            }
//            return filteredKeys.toArray(new String[filteredKeys.size()]);
//        } else {
//            return new String[] {};
//        }
//    }
//    
//    public void destroy() {
//        List<Exporter<?>> exporters = new ArrayList<Exporter<?>>(bounds.values());
//        for(Exporter<?> exporter :exporters){
//            exporter.unexport();
//        }
//        bounds.clear();
//    }
//    
//    
//    /*重新export 1.protocol中的exporter destory问题 
//     *1.要求registryprotocol返回的exporter可以正常destroy
//     *2.notify后不需要重新向注册中心注册 
//     *3.export 方法传入的invoker最好能一直作为exporter的invoker.
//     */
//    private class OverrideListener implements NotifyListener {
//    	
//    	private volatile List<Configurator> configurators;
//    	
//    	private final URL subscribeUrl;
//
//		public OverrideListener(URL subscribeUrl) {
//			this.subscribeUrl = subscribeUrl;
//		}
//
//		/*
//         *  provider 端可识别的override url只有这两种.
//         *  override://0.0.0.0/serviceName?timeout=10
//         *  override://0.0.0.0/?timeout=10
//         */
//        public void notify(List<URL> urls) {
//        	List<URL> result = null;
//        	for (URL url : urls) {
//        		URL overrideUrl = url;
//        		if (url.getParameter(Constants.CATEGORY_KEY) == null
//        				&& Constants.OVERRIDE_PROTOCOL.equals(url.getProtocol())) {
//        			// 兼容旧版本
//        			overrideUrl = url.addParameter(Constants.CATEGORY_KEY, Constants.CONFIGURATORS_CATEGORY);
//        		}
//        		if (! UrlUtils.isMatch(subscribeUrl, overrideUrl)) {
//        			if (result == null) {
//        				result = new ArrayList<URL>(urls);
//        			}
//        			result.remove(url);
//        			logger.warn("Subsribe category=configurator, but notifed non-configurator urls. may be registry bug. unexcepted url: " + url);
//        		}
//        	}
//        	if (result != null) {
//        		urls = result;
//        	}
//        	this.configurators = RegistryDirectory.toConfigurators(urls);
//            List<ExporterChangeableWrapper<?>> exporters = new ArrayList<ExporterChangeableWrapper<?>>(bounds.values());
//            for (ExporterChangeableWrapper<?> exporter : exporters){
//                Invoker<?> invoker = exporter.getOriginInvoker();
//                final Invoker<?> originInvoker ;
//                if (invoker instanceof InvokerDelegete){
//                    originInvoker = ((InvokerDelegete<?>)invoker).getInvoker();
//                }else {
//                    originInvoker = invoker;
//                }
//                
//                URL originUrl = RegistryProtocol.this.getProviderUrl(originInvoker);
//                URL newUrl = getNewInvokerUrl(originUrl, urls);
//                
//                if (! originUrl.equals(newUrl)){
//                    RegistryProtocol.this.doChangeLocalExport(originInvoker, newUrl);
//                }
//            }
//        }
//        
//        private URL getNewInvokerUrl(URL url, List<URL> urls){
//        	List<Configurator> localConfigurators = this.configurators; // local reference
//            // 合并override参数
//            if (localConfigurators != null && localConfigurators.size() > 0) {
//                for (Configurator configurator : localConfigurators) {
//                    url = configurator.configure(url);
//                }
//            }
//            return url;
//        }
//    }
//    
//    public static class InvokerDelegete<T> extends InvokerWrapper<T>{
//        private final Invoker<T> invoker;
//        /**
//         * @param invoker 
//         * @param url invoker.getUrl返回此值
//         */
//        public InvokerDelegete(Invoker<T> invoker, URL url){
//            super(invoker, url);
//            this.invoker = invoker;
//        }
//        public Invoker<T> getInvoker(){
//            if (invoker instanceof InvokerDelegete){
//                return ((InvokerDelegete<T>)invoker).getInvoker();
//            } else {
//                return invoker;
//            }
//        }
//    }
//    
//    /**
//     * exporter代理,建立返回的exporter与protocol export出的exporter的对应关系，在override时可以进行关系修改.
//     * 
//     * @author chao.liuc
//     *
//     * @param <T>
//     */
//    private class ExporterChangeableWrapper<T> implements Exporter<T>{
//    	
//        private Exporter<T> exporter;
//        
//        private final Invoker<T> originInvoker;
//
//        public ExporterChangeableWrapper(Exporter<T> exporter, Invoker<T> originInvoker){
//            this.exporter = exporter;
//            this.originInvoker = originInvoker;
//        }
//        
//        public Invoker<T> getOriginInvoker() {
//            return originInvoker;
//        }
//
//        public Invoker<T> getInvoker() {
//            return exporter.getInvoker();
//        }
//        
//        public void setExporter(Exporter<T> exporter){
//            this.exporter = exporter;
//        }
//
//        public void unexport() {
//            String key = getCacheKey(this.originInvoker);
//            bounds.remove(key);
//            exporter.unexport();
//        }
//    }
//}